package com.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;



/**
 * excel上传文件包装类
 * 屏蔽文件保存和excel解析细节
 */
public class ExcelMultipartFile implements MultipartFile {
	
	private static Logger logger = LoggerFactory.getLogger(ExcelMultipartFile.class);
	
	//上传文件名自增序列，防止并发重复文件名
	private final static AtomicLong UNIQUE_UPLOAD_INDEX = new AtomicLong(10000);
	
	public static final String OFFICE_EXCEL_2003_POSTFIX = "xls";//2003excel后缀
	
	public static final String OFFICE_EXCEL_2007_POSTFIX = "xlsx";//2007excel后缀
	//上传的文件
	private MultipartFile multipartFile;
	//excel业务类型
	private String bizType;
	private HttpServletRequest request;
	
	/**
	 * 
	 * @param request
	 * @param multipartFile - MultipartFile
	 * @param bizType - 上传excel的业务类型
	 */
	public ExcelMultipartFile(HttpServletRequest request,MultipartFile multipartFile,String bizType)
	{
		this.multipartFile = multipartFile;
		this.bizType = bizType;
		this.request = request;
	}
	
	@Override
	public String getName() {
		return multipartFile.getName();
	}

	@Override
	public String getOriginalFilename() {
		return multipartFile.getOriginalFilename();
	}

	@Override
	public String getContentType() {
		return multipartFile.getContentType();
	}

	@Override
	public boolean isEmpty() {
		return multipartFile.isEmpty();
	}

	@Override
	public long getSize() {
		return multipartFile.getSize();
	}

	@Override
	public byte[] getBytes() throws IOException {
		return multipartFile.getBytes();
	}

	@Override
	public InputStream getInputStream() throws IOException {
		return multipartFile.getInputStream();
	}

	@Override
	public void transferTo(File dest) throws IOException, IllegalStateException {
		multipartFile.transferTo(dest);
	}
	
	/**
	 * 返回解释好的excel数据
	 * 自动保存文件到相应目录
	 * 遇空白列会结束
	 * @return
	 */
	public ExcelInfo getExcelInfo() {
		return this.getExcelInfo(true);
	}
	
	/**
	 * 返回解释好的excel数据
	 * 自动保存文件到相应目录
	 * 以表头为准，会处理空白列
	 * @return
	 */
	public ExcelInfo getExcelInfoWithBlankCol()
	{
		return this.getExcelInfo(false);
	}
	
	/**
	 * 返回解释好的excel数据
	 * 自动保存文件到相应目录
	 * @return
	 */
	private ExcelInfo getExcelInfo(boolean isEndEithBlankCol)
	{
		StringBuilder sb = new StringBuilder();
		
		sb.append(request.getServletContext().getRealPath("/"));
		sb.append("res/");
		
		StringBuilder relativeStoragePathSb = new StringBuilder();
		relativeStoragePathSb.append(this.bizType);//
		relativeStoragePathSb.append("/");
		relativeStoragePathSb.append(DateUtil.getNowDateStrYYMMDD());
		relativeStoragePathSb.append("/");
		
		sb.append(relativeStoragePathSb.toString());
		
		ExcelInfo excelInfo = new ExcelInfo();
		
		//文件名
		StringBuilder excelFileNameSb = new StringBuilder();
		excelFileNameSb.append(DateUtil.getNowDateStrYMDHMS());
		//返回毫微秒的时间
		excelFileNameSb.append(System.nanoTime());
		excelFileNameSb.append(getUniqueUploadIndex());
		String suffix =multipartFile.getOriginalFilename().substring  
		(multipartFile.getOriginalFilename().lastIndexOf(".")); 
		excelFileNameSb.append(suffix);
		String excelFileName = excelFileNameSb.toString();
		String newFileName = null;
		
		try {
			//保存文件到服务器
			String uploadPath = sb.toString();
			
			File uploadPathFile = new File(uploadPath);
			if (!uploadPathFile.exists())
			{
				uploadPathFile.mkdirs();
			}
			
			newFileName = uploadPath.concat(excelFileName);
			logger.debug("save import excel file path:{}",newFileName);
			
			File toWriteExcel = new File(newFileName);

			FileCopyUtils.copy(this.getBytes(), toWriteExcel);
			relativeStoragePathSb.append(excelFileName);
			String relativeStoragePath = relativeStoragePathSb.toString();
			excelInfo.setStoragePath(uploadPath);
			excelInfo.setStorageName(excelFileName);
			excelInfo.setRelativeStoragePath(relativeStoragePath);
		} catch (Exception e) {
			logger.error("create upload file error:{}",e.getMessage());
			return null;
		}
		
		List<List<String>> resultList = new ArrayList<List<String>>();
		
		try {
			//提取excel内容转换
			 Workbook wb=WorkbookFactory.create(new FileInputStream(newFileName));
			 Sheet sh=wb.getSheetAt(0);
			 Row ro=null;
			 Cell cell;
			 //excel第一行数据的列数
			 int firstCellCount = 0;
			 for (int i=0; sh.getRow(i)!=null; i++)
			 { 
				 ro = sh.getRow(i);
				 if(null==ro){
					 break;
				 }
				 if (i==0)
				 {
					 firstCellCount = ro.getLastCellNum();
					 excelInfo.setCellNum(firstCellCount);
				 }
				 
				 //列
				 List<String> rowList = new ArrayList<String>(firstCellCount);
				 for (int j=0; j<firstCellCount; j++)
				 {
					cell = ro.getCell(j);
					if (cell == null) {
						if (isEndEithBlankCol) {// 遇空白列结束
							break;// 不放入空的垃圾数据
						} else {
							rowList.add(null);
						}
					} else {
						cell.setCellType(Cell.CELL_TYPE_STRING);
						if (StringUtils.isNotEmpty(cell.getStringCellValue())) {
							rowList.add(cell.getStringCellValue().toString().trim());
						} else {
							rowList.add("");
						}
					}
				 }
				 //不放入空的垃圾数据
				 if (rowList.size()>0) resultList.add(rowList);
			 }
			 logger.debug("resultList:{}",resultList);
			 excelInfo.setRows(resultList);
			 
		} catch (FileNotFoundException e) {
			logger.error(e.getMessage());
		} catch (IOException e) {
			logger.error(e.getMessage());
		} catch (InvalidFormatException e) {
			e.printStackTrace();
		} 
		
		return excelInfo;
	}
	
	/**
	 * 获取自增数
	 * @return
	 */
	private static long getUniqueUploadIndex()
	{
		long t = UNIQUE_UPLOAD_INDEX.getAndIncrement();
		
		if (t>99999)//超过99999归10000
		{
			UNIQUE_UPLOAD_INDEX.compareAndSet(99999, 10000);
		}
		
		return t;
	}
	
	/**
	 * 上传的excel数据信息
	 */
	public class ExcelInfo
	{
		//excel数据行
		private List<List<String>> rows;
		
		//excel列数
		private Integer cellNum; 
		
		//存储路径
		private String storagePath;
		
		/**
		 * 相对路径
		 */
		private String relativeStoragePath;
		
		//储存名字
		private String storageName;
		
		@Deprecated
		public List<List<String>> getRows() {
			return rows;
		}
		
		public void setRows(List<List<String>> rows) {
			this.rows = rows;
		}
		public String getStoragePath() {
			return storagePath;
		}
		public void setStoragePath(String storagePath) {
			this.storagePath = storagePath;
		}
		public String getStorageName() {
			return storageName;
		}
		public void setStorageName(String storageName) {
			this.storageName = storageName;
		}
		public String getRelativeStoragePath() {
			return relativeStoragePath;
		}
		public void setRelativeStoragePath(String relativeStoragePath) {
			this.relativeStoragePath = relativeStoragePath;
		}

		public Integer getCellNum() {
			return cellNum;
		}

		public void setCellNum(Integer cellNum) {
			this.cellNum = cellNum;
		}
		
	}
}






